package com.pig4cloud.pigx.contract.websocket.subscribe;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.pig4cloud.pigx.common.websocket.holder.SessionKeyGenerator;
import com.pig4cloud.pigx.contract.dto.AppContractCurrentPositionConditionDTO;
import com.pig4cloud.pigx.contract.enums.ContractOrderEnum;
import com.pig4cloud.pigx.contract.enums.ContractPositionEnum;
import com.pig4cloud.pigx.contract.mapper.ContractPositionMapper;
import com.pig4cloud.pigx.contract.mongo.entity.ContractSymbolMongo;
import com.pig4cloud.pigx.contract.utils.ContractUtils;
import com.pig4cloud.pigx.contract.vo.AbstractTopicVO;
import com.pig4cloud.pigx.contract.vo.AppContractCurrentPositionVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.web.socket.WebSocketSession;

import java.math.RoundingMode;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 */
@Slf4j
@Component
public class CurrentPosition extends DataListAbstractTopic {

	private final SessionKeyGenerator sessionKeyGenerator;
	private final ContractPositionMapper contractPositionMapper;
	private final ContractUtils utils;

	private final MongoTemplate mongo;

	protected String TOPICNAME = "currentPosition";

	public CurrentPosition(SessionKeyGenerator sessionKeyGenerator, ContractPositionMapper contractPositionMapper, ContractUtils utils, MongoTemplate mongo) {
		this.sessionKeyGenerator = sessionKeyGenerator;
		this.contractPositionMapper = contractPositionMapper;
		this.utils = utils;
		this.mongo = mongo;
		init();
	}

	private void init() {
		wsPush();
	}

	private void wsPush() {
		ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
		service.scheduleAtFixedRate(() -> {
			try {
				for (Map.Entry<WebSocketSession, AbstractTopicVO> entry : subList.entrySet()) {
					try {
						if (!entry.getKey().isOpen()) {
							subList.remove(entry.getKey());
							log.info("ws 移除已关闭的session");
							continue;
						}

						Object userId = sessionKeyGenerator.sessionKey(entry.getKey());
						List<String> dataList = entry.getValue().getDataList();

						AppContractCurrentPositionConditionDTO condition = new AppContractCurrentPositionConditionDTO();
						condition.setUserId(Long.valueOf(userId.toString()));
						// 币对id
						if (!CollectionUtils.isEmpty(dataList)) {
							String symbolId = dataList.get(1);
							String isAll = dataList.get(2);
							if (Strings.isNotEmpty(symbolId) && Strings.isNotEmpty(isAll)) {
								condition.setSymbolId(Long.valueOf(symbolId));
							}
						}

						// 查询数据
						List<AppContractCurrentPositionVO> voList = contractPositionMapper.appListCurrentPosition(condition);
						// 遍历
						voList.forEach(vo -> {
							// 计算未实现盈亏、收益率，设置标记价
							utils.computeFloatProfit(vo);
							// 计算页面保证金和保证金率
							utils.computeMarginRate(vo);

							// 计算可用数量（USDT）
							vo.setAvailableMainCurNum(vo.getAvailableNum().multiply(vo.getOpenAvgPrice()));
							vo.setUNowNum(vo.getNowNum().multiply(vo.getMarkPrice()));
							vo.setUAvailableNum(vo.getAvailableNum().multiply(vo.getMarkPrice()));
							vo.setUClosingNum(vo.getClosingNum().multiply(vo.getMarkPrice()));

							// 张数
							ContractSymbolMongo one = mongo.findOne(Query.query(Criteria.where("name").is(vo.getSymbolName())), ContractSymbolMongo.class);
							if (one != null) {
								vo.setSheet(one.getSheet());
							}

							// 设置精度
							utils.setScaleBySymbol(vo, vo.getSymbolName());

							// 未实现盈亏先默认2位精度
							vo.setFloatProfit(vo.getFloatProfit().setScale(2, RoundingMode.HALF_UP));

							// 翻译字典项
							vo.setMode(ContractPositionEnum.Mode.findName(vo.getMode()));
							vo.setSide(ContractOrderEnum.Side.findName(vo.getSide()));
							vo.setStatus(ContractPositionEnum.Status.findName(vo.getStatus()));
						});

						JSONArray array = JSONArray.parseArray(JSON.toJSONString(voList));
						entry.getKey().sendMessage(getTextMessage(dataList, array));

					} catch (Exception ex) {
						ex.printStackTrace();
						log.info("push current position err:" + ex.getMessage());
					} finally {
						// 清空localThread币对缓存
						ContractUtils.removeSymbolThreadCache();
					}
				}

			} catch (Throwable e) {
				e.printStackTrace();
				log.info("push current position err:" + e.getMessage());
			}

		}, 0, 1500, TimeUnit.MILLISECONDS);
	}
}
